<template>
<div class="app-container">
<el-card shadow="never" class="panel">
<div slot="header" class="panel__header"><i class="el-icon-cpu panel__icon"></i><div class="panel__title">设备访问控制</div></div>


<el-form :inline="true" :model="q" class="mb12">
<el-form-item label="状态"><el-select v-model="q.status" clearable placeholder="全部"><el-option label="启用" value="enabled"/><el-option label="禁用" value="disabled"/></el-select></el-form-item>
<el-form-item label="关键字"><el-input v-model="q.keyword" placeholder="名称/编号" clearable/></el-form-item>
<el-form-item><el-button type="primary" icon="el-icon-search" @click="fetch">查询</el-button><el-button @click="reset" icon="el-icon-refresh">重置</el-button></el-form-item>
<el-form-item><el-button type="primary" icon="el-icon-plus" @click="openEdit()">新增设备</el-button></el-form-item>
</el-form>


<el-table :data="list" border stripe v-loading="loading" @selection-change="sels=>selections=sels">
<el-table-column type="selection" width="48"/>
<el-table-column prop="name" label="设备名称" min-width="160"/>
<el-table-column prop="code" label="编号" width="160"/>
<el-table-column prop="status" label="状态" width="100">
<template slot-scope="s"><el-tag :type="s.row.status==='enabled'?'success':'info'">{{ s.row.status==='enabled'?'启用':'禁用' }}</el-tag></template>
</el-table-column>
<el-table-column label="操作" width="240">
<template slot-scope="s">
<el-button type="text" @click="openEdit(s.row)">编辑</el-button>
<el-button type="text" @click="openPolicy(s.row)">策略</el-button>
<el-button type="text" @click="toggle(s.row)">{{ s.row.status==='enabled'?'禁用':'启用' }}</el-button>
</template>
</el-table-column>
</el-table>


<div class="opbar">
<el-button :disabled="!selections.length" @click="batchPolicy" icon="el-icon-setting">批量设置策略</el-button>
</div>
</el-card>


<!-- 编辑设备 -->
<el-dialog :visible.sync="dlgEdit" :title="editForm.id?'编辑设备':'新增设备'" width="520px">
<el-form ref="editRef" :model="editForm" :rules="editRules" label-width="92px">
<el-form-item label="名称" prop="name"><el-input v-model="editForm.name"/></el-form-item>
<el-form-item label="编号" prop="code"><el-input v-model="editForm.code"/></el-form-item>
</el-form>
<div slot="footer">
<el-button @click="dlgEdit=false">取 消</el-button>
<el-button type="primary" :loading="saving" @click="save">保 存</el-button>
</div>
</el-dialog>


<!-- 策略配置 -->
<el-drawer :visible.sync="drawerPolicy" title="访问策略" size="40%">
<el-form :model="policy" label-width="92px">
<el-form-item label="动作"><el-select v-model="policy.action"><el-option label="读" value="read"/><el-option label="写" value="write"/></el-select></el-form-item>
<el-form-item label="效果"><el-select v-model="policy.effect"><el-option label="允许" value="allow"/><el-option label="拒绝" value="deny"/></el-select></el-form-item>
<el-form-item label="主体"><el-input v-model="policy.subject" placeholder="user:1 / role:admin / did:xxx"/></el-form-item>
<el-form-item label="说明"><el-input v-model="policy.description" type="textarea" :rows="3"/></el-form-item>
<el-button type="primary" :loading="saving" @click="savePolicy">保存策略</el-button>
</el-form>


<el-divider></el-divider>
<el-table :data="policyList" size="small" border>
<el-table-column type="index" width="50"/>
<el-table-column prop="action" label="动作" width="80"/>
<el-table-column prop="effect" label="效果" width="80"/>
<el-table-column prop="subject" label="主体"/>
<el-table-column prop="description" label="说明"/>
<el-table-column label="操作" width="100">
<template slot-scope="s"><el-button type="text" @click="delPolicy(s.row)">删除</el-button></template>
</el-table-column>
</el-table>
</el-drawer>
</div>
</template>


<script>
import request from '@/utils/request'
export default { name:'DeviceAccess', data(){ return{ q:{status:'',keyword:''}, list:[], loading:false, selections:[], dlgEdit:false, drawerPolicy:false, editForm:{}, saving:false, editRules:{ name:[{required:true,message:'必填'}], code:[{required:true,message:'必填'}]}, policy:{ action:'read', effect:'allow', subject:'', description:'' }, policyList:[], curDevice:null } }, methods:{ async fetch(){ this.loading=true; try{ const res= await request({ url:'/device/list', method:'get', params:this.q }); this.list=res.rows||[] }finally{ this.loading=false } }, reset(){ this.q={status:'',keyword:''}; this.fetch() }, openEdit(row){ this.editForm=row?{...row}:{ name:'', code:'' }; this.dlgEdit=true }, async save(){ this.$refs.editRef.validate(async ok=>{ if(!ok) return; this.saving=true; try{ await request({ url:'/device/save', method:'post', data:this.editForm }); this.$message.success('保存成功'); this.dlgEdit=false; this.fetch() }finally{ this.saving=false } }) }, toggle(row){ request({ url:'/device/toggle', method:'post', data:{ id:row.id }}).then(()=>{ this.$message.success('已切换'); this.fetch() }) }, openPolicy(row){ this.curDevice=row; this.drawerPolicy=true; this.loadPolicy() }, async loadPolicy(){ const res= await request({ url:'/access/rule/list', method:'get', params:{ resource_type:'device', resource_id:this.curDevice.id } }); this.policyList=res.rows||[] }, async savePolicy(){ if(!this.curDevice) return; this.saving=true; try{ await request({ url:'/access/rule/create', method:'post', data:{ ...this.policy, resource_type:'device', resource_id:this.curDevice.id } }); this.$message.success('策略已保存'); this.loadPolicy() }finally{ this.saving=false } }, async delPolicy(r){ await request({ url:'/access/rule/delete', method:'post', data:{ id:r.id } }); this.$message.success('已删除'); this.loadPolicy() }, batchPolicy(){ if(!this.selections.length) return; this.openPolicy(this.selections[0]) } }, mounted(){ this.fetch() } }
</script>


<style scoped>
.panel{ border:1px solid #ebeef5 }
.panel__header{ display:flex; align-items:center; gap:8px }
.panel__icon{ color:#5d86ff }
.mb12{ margin-bottom:12px }
.opbar{ margin-top:12px }
</style>